package com.bnzj.core.quartz;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;

import com.bnzj.core.quartz.log.JobLog;
import com.bnzj.core.quartz.log.JobLogService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.factory.annotation.Autowired;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @author barry
 * @see org.springframework.scheduling.quartz.QuartzJobBean
 */
@Slf4j
public abstract class BaseQuartzJob implements Job {
	
    @Autowired
    protected JobLogService jobLogService;
    
    private boolean enabledLog;

	/**
	 * This implementation applies the passed-in job data map as bean property
	 * values, and delegates to {@code executeInternal} afterwards.
	 * @see #executeInternal
	 */
	@Override
	public final void execute(JobExecutionContext context) throws JobExecutionException {
	    String triggerName = context.getTrigger().getKey().getName();
        String jobName = context.getJobDetail().getKey().getName();
        String desc = context.getJobDetail().getDescription();
        log.debug("开始执行Job：{}---{}---{}", triggerName, jobName, desc);
		try {
			BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
			MutablePropertyValues pvs = new MutablePropertyValues();
			pvs.addPropertyValues(context.getScheduler().getContext());
			pvs.addPropertyValues(context.getMergedJobDataMap());
			bw.setPropertyValues(pvs, true);
		} catch (SchedulerException e) {
			throw new JobExecutionException(e);
		}
        JobLog jobLog = jobLogService.createJobLog();
        long startTime=System.currentTimeMillis();
		try {
			executeInternal(context);
            if (isEnabledLog()) {
                jobLog.setFlag(true);
                jobLog.setRemark("SUCCESS");
            }
		} catch (Exception e) {//e.printStackTrace();
            if (isEnabledLog()) {
                jobLog.setFlag(false);
                StringWriter sw = new StringWriter();
                e.printStackTrace(new PrintWriter(sw));
                jobLog.setRemark(sw.toString());
                try {
                    sw.close();
                } catch (IOException e1) {
                }
            }
            if(e instanceof JobExecutionException) {
                throw e;
            }
			throw new JobExecutionException(e);
		}finally {
	        long endTime = System.currentTimeMillis();
	        if(isEnabledLog()) {
                jobLog.setName(jobName);// 获得任务名称
	            jobLog.setDescription(desc);
                //String triggerName = "manualTrigger";//手动执行
	            jobLog.setTriggerName(triggerName);
	            float runTime = (float)(endTime - startTime) / 1000;
                jobLog.setRunTime(runTime);
                jobLog.setStartTime(new Date(startTime));
                jobLog.setEndTime(new Date(endTime));
	            jobLogService.add(jobLog);
	        }
            log.debug("执行Job完毕：{}---{}---{}", triggerName, jobName, desc);
        }
	}

	/**
	 * Execute the actual job. The job data map will already have been
	 * applied as bean property values by execute. The contract is
	 * exactly the same as for the standard Quartz execute method.
	 * @see #execute
	 */
	protected abstract void executeInternal(JobExecutionContext context) throws JobExecutionException;

    public boolean isEnabledLog() {
        return enabledLog;
    }

    protected void setEnabledLog(boolean enabledLog) {
        this.enabledLog = enabledLog;
    }
}
